<?php

namespace app\api\controller\v1;

use app\common\controller\Api;
use app\admin\model\Ocation;
use think\Exception;
use think\Db;

/**
 * AI助手API控制器
 */
class AiHelper extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    /**
     * AI配置
     */
    private $aiConfig;

    // Add to your _initialize method
    protected $model;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\Ocation();

        // 加载AI配置
        try {
            $this->aiConfig = config('ai');
            if (!$this->aiConfig) {
                $this->aiConfig = [
                    'default_text_provider' => 'qianwen',
                    'qianwen' => [
                        'api_key' => 'sk-59c3d578ae0e411bab5447cd85254961',
                        'text_api_url' => 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation',
                        'text_model' => 'qwen-turbo'
                    ]
                ];
            }
        } catch (\Exception $e) {
            $this->aiConfig = [];
        }
    }

    /**
     * AI文本生成
     */
    public function generateText()
    {
        if (!$this->request->isPost()) {
            return json(['code' => 0, 'msg' => '请求方式错误']);
        }

        $prompt = $this->request->post('prompt', '');
        $type = $this->request->post('type', 'general');
        $maxTokens = $this->request->post('max_tokens', 3000);
        $temperature = $this->request->post('temperature', 0.7);
        $provider = $this->request->post('provider', 'qianwen');

        if (empty($prompt)) {
            return json(['code' => 0, 'msg' => '提示词不能为空']);
        }

        try {
            // 确保输入的UTF-8编码正确性
            $prompt = $this->sanitizeUTF8($prompt);

            // 如果是班级介绍类型，尝试增强提示词
            if ($type === 'class_intro') {
                $prompt = $this->enhanceClassIntroPrompt($prompt);
            }

            // 记录请求日志
            $this->writeLog("AI文本生成请求: " . substr($prompt, 0, 100) . "...");

            // 调用AI文本生成服务
           $generatedText = $this->callTextGenerationApi($prompt, $maxTokens, $temperature, $provider);

            if ($generatedText) {
                // 确保输出的UTF-8编码正确性
                $generatedText = $this->sanitizeUTF8($generatedText);
                
                $this->writeLog("AI文本生成成功，长度: " . mb_strlen($generatedText));
                //文本回车转<p>
                $generatedText = str_replace('\n', '<p>', $generatedText);
                $generatedText =preg_replace("/^```(.*?)$/Uimx","",$generatedText);
                $generatedText =preg_replace("/^<br>\s*$/Uimx","<p>$1</p>",$generatedText);
                $generatedText =preg_replace("/^\s*$/Uimx","",$generatedText);
                return json([
                    'code' => 1,
                    'msg' => 'AI文本生成成功',
                    'data' => [
                        'content' => $generatedText,
                        'prompt' => $this->sanitizeUTF8($prompt),
                        'type' => $type,
                        'provider' => $provider,
                        'tokens_used' => mb_strlen($generatedText)
                    ]
                ]);
            } else {
                $this->writeLog("AI文本生成失败：返回内容为空", 'error');
                return json(['code' => 0, 'msg' => 'AI文本生成失败：返回内容为空']);
            }
        } catch (\Exception $e) {
            $this->writeLog("文本生成错误: " . $e->getMessage(), 'error');

            // 如果是账户欠费或API调用失败，返回模拟内容
            if (strpos($e->getMessage(), 'Arrearage') !== false ||
                strpos($e->getMessage(), 'Access denied') !== false ||
                strpos($e->getMessage(), 'API请求失败') !== false) {

                $this->writeLog("API调用失败，使用模拟内容", 'warning');
                $mockContent = $this->generateMockContent($prompt);

                // 确保模拟内容的UTF-8编码正确性
                $mockContent = $this->sanitizeUTF8($mockContent);

                return json([
                    'code' => 1,
                    'msg' => 'AI文本生成成功（模拟模式）',
                    'data' => [
                        'content' => $mockContent,
                        'prompt' => $this->sanitizeUTF8($prompt),
                        'type' => $type,
                        'provider' => $provider . '_mock',
                        'tokens_used' => mb_strlen($mockContent),
                        'note' => 'API调用失败，使用模拟内容'
                    ]
                ]);
            }

            // 检查错误信息是否包含服务商信息，如果包含则直接返回，否则添加通用错误信息
            $errorMsg = $e->getMessage();
            if (strpos($errorMsg, '最后尝试的服务商') !== false) {
                return json(['code' => 0, 'msg' => $errorMsg]);
            } else {
                return json(['code' => 0, 'msg' => 'AI文本生成失败: ' . $errorMsg]);
            }
        }
    }

    /**
     * 获取教学点课程信息
     */
    public function getOcationCourses()
    {
        if (!$this->request->isPost()) {
            return json(['code' => 0, 'msg' => '请求方式错误']);
        }

        $ocationId = $this->request->post('ocation_id', '');

        if (empty($ocationId)) {
            return json(['code' => 0, 'msg' => '教学点ID不能为空']);
        }

        try {
            // 获取教学点课程信息
            $coursesData = $this->getOcationCoursesData($ocationId);

            return json([
                'code' => 1,
                'msg' => '课程信息获取成功',
                'data' => $coursesData
            ]);
        } catch (\Exception $e) {
            $this->writeLog("获取教学点课程信息错误: " . $e->getMessage(), 'error');
            return json(['code' => 0, 'msg' => '获取课程信息失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 简单测试方法
     */
    public function simpleTest()
    {
        return json([
            'code' => 1,
            'msg' => '简单测试成功',
            'data' => [
                'time' => date('Y-m-d H:i:s'),
                'utf8_test' => $this->sanitizeUTF8('测试UTF-8编码：中文字符')
            ]
        ]);
    }

    /**
     * 调用文本生成API（支持多服务商自动切换）
     */
    private function callTextGenerationApi($prompt, $maxTokens, $temperature, $provider)
    {
        // 文本生成的服务商优先级
        $textProviderPriority = ['qianwen'];

        // 获取当前服务商
        $currentProvider = $provider ?: 'qianwen';
        $maxAttempts = count($textProviderPriority);
        $lastTriedProvider = $currentProvider; // 记录最后尝试的服务商

        for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
            try {
                $this->writeLog("文本生成第 {$attempt} 次尝试，使用服务商: {$currentProvider}");
                $lastTriedProvider = $currentProvider; // 更新最后尝试的服务商

                // 根据服务商调用对应的API
                switch ($currentProvider) {
                    case 'qianwen':
                        $result = $this->callQianwenApi($prompt, $maxTokens, $temperature);
                        break;
                    default:
                        throw new \Exception("不支持的文本生成服务商: {$currentProvider}");
                }

                if ($result) {
                    $this->writeLog("文本生成成功，服务商: {$currentProvider}");
                    return $result;
                }

            } catch (\Exception $e) {
                $this->writeLog("服务商 {$currentProvider} 文本生成失败: " . $e->getMessage(), 'error');

                // 如果不是最后一次尝试，切换到下一个服务商
                if ($attempt < $maxAttempts) {
                    $nextProvider = $this->getNextTextProvider($currentProvider, $textProviderPriority);
                    if ($nextProvider) {
                        $currentProvider = $nextProvider;
                        $this->writeLog("切换到备用文本生成服务商: {$currentProvider}");
                        continue;
                    } else {
                        $this->writeLog("无更多备用文本生成服务商可用");
                        break;
                    }
                }
            }
        }

        // 所有服务商都失败时，抛出包含最后尝试服务商名称的异常
        $providerNames = [
            'qianwen' => '阿里千问'
        ];
        $lastProviderName = $providerNames[$lastTriedProvider] ?? $lastTriedProvider;

        throw new \Exception("所有AI文本生成服务商均不可用，最后尝试的服务商：{$lastProviderName}");
    }

    /**
     * 获取下一个文本生成服务商
     */
    private function getNextTextProvider($currentProvider, $providerPriority)
    {
        $currentIndex = array_search($currentProvider, $providerPriority);

        if ($currentIndex === false) {
            $currentIndex = 0;
        }

        // 获取下一个服务商
        $nextIndex = $currentIndex + 1;
        if ($nextIndex >= count($providerPriority)) {
            return null; // 无更多备用
        }

        return $providerPriority[$nextIndex];
    }

    /**
     * 调用千问AI文本生成API
     */
    private function callQianwenApi($prompt, $maxTokens, $temperature)
    {
        $apiKey = $this->aiConfig['qianwen']['api_key'] ?? '';
        $apiUrl = $this->aiConfig['qianwen']['text_api_url'] ?? 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation';
        $model = $this->aiConfig['qianwen']['text_model'] ?? 'qwen-turbo';

        if (empty($apiKey)) {
            throw new \Exception('千问API密钥未配置');
        }

        $this->writeLog("调用千问API: {$apiUrl}");

        $data = [
            'model' => $model,
            'input' => [
                'messages' => [
                    [
                        'role' => 'user',
                        'content' => $prompt
                    ]
                ]
            ],
            'parameters' => [
                'max_tokens' => (int)$maxTokens,
                'temperature' => (float)$temperature
            ]
        ];

        $headers = [
            'Authorization: Bearer ' . $apiKey,
            'Content-Type: application/json'
        ];

        $this->writeLog("千问API请求数据: " . json_encode($data, JSON_UNESCAPED_UNICODE));

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        $this->writeLog("千问API响应状态: " . $httpCode);
        $this->writeLog("千问API响应内容: " . substr($response, 0, 500) . "...");

        if ($error) {
            throw new \Exception('cURL错误: ' . $error);
        }

        if ($httpCode !== 200) {
            throw new \Exception('千问API请求失败，HTTP状态码: ' . $httpCode . '，响应: ' . $response);
        }

        $result = json_decode($response, true);
        if (isset($result['output']['text'])) {
            return trim($result['output']['text']);
        }

        throw new \Exception('千问API返回格式错误: ' . $response);
    }

    /**
     * 生成模拟内容
     */
    private function generateMockContent($prompt)
    {
        // 分析提示词类型
        if (strpos($prompt, '班级介绍') !== false || strpos($prompt, 'class_intro') !== false) {
            return $this->generateMockClassIntro($prompt);
        } elseif (strpos($prompt, '教学点') !== false || strpos($prompt, 'ocation') !== false) {
            return $this->generateMockOcationDetail($prompt);
        } else {
            return $this->generateMockGeneralContent($prompt);
        }
    }

    /**
     * 获取或生成教学点介绍
     */
    public function getOrGenerateOcationIntro()
    {
        $ocation_id = $this->request->param('ocation_id/d');

        if (!$ocation_id) {
            return json(['code' => 0, 'msg' => '缺少教学点ID,请先排课']);
        }

        try {
            // 查询教学点信息
            $ocation = \think\Db::name('fa_ocation')
                ->where('id', $ocation_id)
                ->find();

            if (!$ocation) {
                return json(['code' => 0, 'msg' => '教学点不存在,请先排课']);
            }

            // 如果已有教学点介绍，直接返回
            if (!empty($ocation['content'])) {
                return json([
                    'code' => 1,
                    'msg' => '获取教学点介绍成功',
                    'data' => [
                        'content' => $ocation['content'],
                        'intro' => $ocation['intro'] ?? '',
                        'generated' => false
                    ]
                ]);
            }

            // 生成教学点介绍
            $contentPrompt = $this->buildOcationContentPrompt($ocation);

            // 生成教学点简介
            $introPrompt = $this->callQianwenApi($contentPrompt, 500, 0.7, 'qianwen');
            //$intro = $this->generateMockOcationDetail($introPrompt);

            // 保存到数据库
            \think\Db::name('fa_ocation')
                ->where('id', $ocation_id)
                ->update([
                    'content' => $introPrompt,
                ]);

            return json([
                'code' => 1,
                'msg' => '教学点介绍生成成功',
                'data' => [
                    'content' => $contentPrompt,
                    'generated' => true
                ]
            ]);

        } catch (\Exception $e) {
            $this->writeLog("获取教学点介绍失败: " . $e->getMessage(), 'error');
            return json(['code' => 0, 'msg' => '获取教学点介绍失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 测试百度地图API接口
     */
    public function testBaiduMapApi()
    {
        $longitude = $this->request->param('longitude', '108.35528564453125');
        $latitude = $this->request->param('latitude', '22.81');

        try {
            $this->writeLog("开始测试百度地图API，坐标: {$longitude}, {$latitude}");

            $locationInfo = $this->getBaiduLocationInfo($longitude, $latitude);

            if ($locationInfo) {
                return json([
                    'code' => 1,
                    'msg' => '百度地图API测试成功',
                    'data' => [
                        'coordinates' => [
                            'longitude' => $longitude,
                            'latitude' => $latitude
                        ],
                        'location_info' => $locationInfo,
                        'formatted_info' => nl2br($locationInfo)
                    ]
                ]);
            } else {
                return json([
                    'code' => 0,
                    'msg' => '百度地图API调用失败，未获取到位置信息',
                    'data' => [
                        'coordinates' => [
                            'longitude' => $longitude,
                            'latitude' => $latitude
                        ],
                        'debug_info' => '请检查API密钥配置和权限设置'
                    ]
                ]);
            }

        } catch (\Exception $e) {
            $this->writeLog("百度地图API测试失败: " . $e->getMessage(), 'error');
            return json([
                'code' => 0,
                'msg' => '百度地图API测试失败: ' . $e->getMessage()
            ]);
        }
    }

    /**
     * 检查百度地图API配置
     */
    public function checkBaiduMapConfig()
    {
        try {
            $baiduConfig = config('ai.baidu_map');

            $configInfo = [
                'enabled' => $baiduConfig['enabled'] ?? false,
                'api_key_configured' => !empty($baiduConfig['api_key']),
                'api_key_length' => !empty($baiduConfig['api_key']) ? strlen($baiduConfig['api_key']) : 0,
                'timeout' => $baiduConfig['timeout'] ?? 10,
                'max_radius' => $baiduConfig['max_radius'] ?? 2000,
                'max_results' => $baiduConfig['max_results'] ?? 10,
                'poi_types' => $baiduConfig['poi_types'] ?? []
            ];

            // 检查API密钥格式
            $apiKeyStatus = 'not_configured';
            if (!empty($baiduConfig['api_key'])) {
                $keyLength = strlen($baiduConfig['api_key']);
                if ($keyLength >= 20 && $keyLength <= 50) {
                    $apiKeyStatus = 'configured';
                } else {
                    $apiKeyStatus = 'invalid_format';
                }
            }

            return json([
                'code' => 1,
                'msg' => '百度地图API配置检查完成',
                'data' => [
                    'config_info' => $configInfo,
                    'api_key_status' => $apiKeyStatus,
                    'config_file' => 'application/extra/ai.php',
                    'recommendations' => $this->getBaiduConfigRecommendations($configInfo, $apiKeyStatus)
                ]
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 0,
                'msg' => '配置检查失败: ' . $e->getMessage()
            ]);
        }
    }

    /**
     * 获取百度地图配置建议
     */
    private function getBaiduConfigRecommendations($configInfo, $apiKeyStatus)
    {
        $recommendations = [];

        if (!$configInfo['enabled']) {
            $recommendations[] = '建议启用百度地图API功能：设置 enabled => true';
        }

        if ($apiKeyStatus === 'not_configured') {
            $recommendations[] = '需要配置百度地图API密钥：设置 api_key 值';
            $recommendations[] = '获取API密钥：访问 https://lbsyun.baidu.com/';
        } elseif ($apiKeyStatus === 'invalid_format') {
            $recommendations[] = 'API密钥格式可能不正确，请检查密钥长度和格式';
        }

        if ($configInfo['timeout'] < 10) {
            $recommendations[] = '建议设置较长的超时时间（至少10秒）以确保API调用稳定';
        }

        if ($configInfo['max_radius'] > 5000) {
            $recommendations[] = '搜索半径过大可能影响性能，建议设置在5000米以内';
        }

        if (empty($configInfo['poi_types'])) {
            $recommendations[] = '建议配置POI类型映射以获得更准确的搜索结果';
        }

        return $recommendations;
    }

    /**
     * 构建教学点内容生成提示词
     */
    private function buildOcationContentPrompt($ocation)
    {
        $prompt = "# 教学点介绍生成任务\n\n";
        $prompt .= "## 教学点基本信息\n";
        $prompt .= "**教学点名称：** " . $ocation['name'] . "\n";

        if (!empty($ocation['address'])) {
            $prompt .= "**地址：** " . $ocation['address'] . "\n";
        }

        // 获取教学点级别
        if (!empty($ocation['address_lv_octionlevel'])) {
            $levelMap = [
                '1' => '一级教学点',
                '2' => '二级教学点',
                '3' => '三级教学点',
                '4' => '上课教室'
            ];
            $level = $levelMap[$ocation['address_lv_octionlevel']] ?? '教学点';
            $prompt .= "**级别：** " . $level . "\n";
        }

        // 调用百度地图接口获取周边信息
        if (!empty($ocation['longitude']) && !empty($ocation['latitude'])) {
            $locationInfo = $this->getBaiduLocationInfo($ocation['longitude'], $ocation['latitude']);
            if ($locationInfo) {
                $prompt .= "\n## 周边环境信息\n";
                $prompt .= $locationInfo . "\n";
            }
        }
        
        //增加教室的类型
        $prompt .= "\n## 教室类型\n";
        $name = model("app\admin\model\Ocation")->getOcation_typeTextAttr($ocation['ocation_type']);
        $prompt.= "**教室类型：** ". $name. "\n";

        // 增加教学点的近期上课的课程类别情况
        $courseInfo = $this->getOcationCourseInfo($ocation['id']);
        if (!empty($courseInfo)) {
            $prompt .= "\n## 近期课程安排\n";
            $prompt .= $courseInfo;
        }
        $prompt.="\n分析近期的课程，说出来主要授课的课程名称即可，不要说具体的时间和地点学费,不要提到 市级 市一级 市二级 教学点ID 学费 收费 等字眼\n";

        // 报名联系电话统一联系 教务处电话：07713160330
        if (!empty($courseInfo)) {
            $prompt .= "报名联系电话统一联系 教务处电话：07713160330, 要说欢迎咨询和报名，不要提到学费\n";
        }

        $prompt .= "\n## 生成要求\n";
        $prompt .= "1. 字数限制：300-500字\n";
        $prompt .= "2. 语言风格：专业、温馨、具有吸引力\n";
        $prompt .= "3. 内容要点：\n";
        $prompt .= "   - 介绍教学点的基本情况和特色包括公交路线、附近商场、附近美食娱乐旅游景点信息\n";
        $prompt .= "   - 突出教学环境和设施优势\n";
        $prompt .= "   - 体现教学点的教育理念和服务特色\n";
        $prompt .= "   - 重点介绍近期课程安排，展现教学活动的丰富性和多样性\n";
        $prompt .= "   - 营造温馨的学习氛围\n";
        $prompt .= "4. 格式：纯文本格式，分段清晰\n";
        $prompt .= "5. 避免：过于夸张的宣传用词，空泛的描述\n\n";
        $prompt .= "6. 将教学点介绍的内容放在后边，放在最后\n\n";
        $prompt .= "根据以上信息，请生成教学点介绍，用自然语言描述，并使用中文。\n";

        return $prompt;
    }

    /**
     * 构建教学点简介生成提示词
     */
    private function buildOcationIntroPrompt($ocation, $content)
    {
        $prompt = "# 教学点简介生成任务\n\n";
        $prompt .= "## 教学点信息\n";
        $prompt .= "**教学点名称：** " . $ocation['name'] . "\n";
        $prompt .= "**详细介绍：** " . $content . "\n\n";
        $prompt .= "## 生成要求\n";
        $prompt .= "1. 字数限制：严格控制在50字以内\n";
        $prompt .= "2. 语言风格：简洁明了，突出重点\n";
        $prompt .= "3. 内容要点：提炼教学点最核心的特色和优势,不要提到 市级 市一级 市二级 教学点ID 学费 收费 等字眼\n";
        $prompt .= "4. 格式：纯文本，一句话概括\n\n";
        $prompt .= "请生成50字以内的教学点简介：";

        return $prompt;
    }

    /**
     * 调用百度地图API获取周边信息
     */
    private function getBaiduLocationInfo($longitude, $latitude)
    {
        try {
            // 从配置文件获取百度地图API密钥
            $baiduConfig = config('ai.baidu_map');
            $apiKey = $baiduConfig['api_key_server'] ?? '';

            if (empty($apiKey)) {
                $this->writeLog("百度地图API密钥未配置", 'warning');
                return null;
            }

            $locationInfo = '';

            // 1. 获取详细地址信息
            $addressInfo = $this->getBaiduAddress($longitude, $latitude, $apiKey);
            if ($addressInfo) {
                $locationInfo .= "**详细地址：** " . $addressInfo . "\n";
            }

            // 获取配置参数
            $maxRadius = $baiduConfig['max_radius'] ?? 2000;
            $maxResults = $baiduConfig['max_results'] ?? 10;
            $timeout = $baiduConfig['timeout'] ?? 30;

            // 2. 获取公交和地铁信息
            $transitInfo = $this->getDetailedTransitInfo($longitude, $latitude, $apiKey, min(1000, $maxRadius), min(5, $maxResults));
            if ($transitInfo) {
                $locationInfo .= $transitInfo;
            }

            // 3. 获取商场购物信息
            $shoppingInfo = $this->getBaiduPOI($longitude, $latitude, $apiKey, '购物', min(2000, $maxRadius), min(3, $maxResults));
            if ($shoppingInfo) {
                $locationInfo .= "**附近商场：** " . $shoppingInfo . "\n";
            }

            // 4. 获取美食信息
            $foodInfo = $this->getBaiduPOI($longitude, $latitude, $apiKey, '美食', min(1500, $maxRadius), min(5, $maxResults));
            if ($foodInfo) {
                $locationInfo .= "**附近美食：** " . $foodInfo . "\n";
            }

            // 5. 获取娱乐信息
            $entertainmentInfo = $this->getBaiduPOI($longitude, $latitude, $apiKey, '娱乐', min(2000, $maxRadius), min(3, $maxResults));
            if ($entertainmentInfo) {
                $locationInfo .= "**休闲娱乐：** " . $entertainmentInfo . "\n";
            }

            // 6. 获取旅游景点信息
            $touristInfo = $this->getBaiduPOI($longitude, $latitude, $apiKey, '旅游景点', min(3000, $maxRadius), min(3, $maxResults));
            if ($touristInfo) {
                $locationInfo .= "**附近景点：** " . $touristInfo . "\n";
            }

            return $locationInfo;

        } catch (\Exception $e) {
            $this->writeLog("百度地图API调用失败: " . $e->getMessage(), 'error');
            return null;
        }
    }

    /**
     * 获取百度地图详细地址
     */
    private function getBaiduAddress($longitude, $latitude, $apiKey)
    {
        try {
            $apiKey="aBIfRNb8MimBirL5RrjJn1WKDGs0jVQE";
            $url = "https://api.map.baidu.com/reverse_geocoding/v3/";
            $params = [
                'ak' => $apiKey,
                'output' => 'json',
                'coordtype' => 'wgs84ll',
                'location' => $latitude . ',' . $longitude
            ];

            $response = $this->httpRequest($url, $params);
            $data = json_decode($response, true);

            // 记录API响应用于调试
            $this->writeLog("百度地址API响应: " . $response, 'debug');

            if ($data && $data['status'] == 0 && isset($data['result']['formatted_address'])) {
                return $data['result']['formatted_address'];
            }

            // 处理API错误
            if ($data && isset($data['status']) && $data['status'] != 0) {
                $errorMsg = $this->getBaiduApiErrorMessage($data['status']);
                $this->writeLog("百度地址API错误 - 状态码: {$data['status']}, 错误信息: {$errorMsg}", 'error');
            }

            return null;
        } catch (\Exception $e) {
            $this->writeLog("获取百度地址失败: " . $e->getMessage(), 'error');
            return null;
        }
    }

    /**
     * 获取百度地图POI信息
     */
    private function getBaiduPOI($longitude, $latitude, $apiKey, $query, $radius = 2000, $pageSize = 5)
    {
        try {
            $url = "https://api.map.baidu.com/place/v2/search";
            $params = [
                'ak' => $apiKey,
                'output' => 'json',
                'query' => $query,
                'location' => $latitude . ',' . $longitude,
                'radius' => $radius,
                'page_size' => $pageSize,
                'page_num' => 0
            ];

            $response = $this->httpRequest($url, $params);
            $data = json_decode($response, true);

            // 记录API响应用于调试
            $this->writeLog("百度POI API响应: " . $response, 'debug');

            if ($data && $data['status'] == 0 && isset($data['results']) && !empty($data['results'])) {
                $poiList = [];
                foreach ($data['results'] as $poi) {
                    $name = $poi['name'];
                    $address = isset($poi['address']) ? $poi['address'] : '';
                    $distance = isset($poi['detail_info']['distance']) ? $poi['detail_info']['distance'] : '';

                    $poiInfo = $name;
                    if ($distance) {
                        $poiInfo .= '(' . round($distance) . 'm)';
                    }
                    $poiList[] = $poiInfo;
                }

                return implode('、', $poiList);
            }

            // 处理API错误
            if ($data && isset($data['status']) && $data['status'] != 0) {
                $errorMsg = $this->getBaiduApiErrorMessage($data['status']);
                $this->writeLog("百度POI API错误 - 查询: {$query}, 状态码: {$data['status']}, 错误信息: {$errorMsg}", 'error');
            }

            return null;
        } catch (\Exception $e) {
            $this->writeLog("获取百度POI失败: " . $e->getMessage(), 'error');
            return null;
        }
    }

    /**
     * HTTP请求方法
     */
    private function httpRequest($url, $params = [], $method = 'GET', $timeout = null)
    {
        // 如果没有指定超时时间，从配置文件获取
        if ($timeout === null) {
            $baiduConfig = config('ai.baidu_map');
            $timeout = $baiduConfig['timeout'] ?? 10;
        }
        $ch = curl_init();

        if ($method == 'GET' && !empty($params)) {
            $url .= '?' . http_build_query($params);
        }

        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        ]);

        if ($method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if (!empty($params)) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
            }
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new \Exception("HTTP请求失败: " . $error);
        }

        if ($httpCode != 200) {
            throw new \Exception("HTTP请求失败，状态码: " . $httpCode);
        }

        return $response;
    }

    /**
     * 获取百度API错误信息
     */
    private function getBaiduApiErrorMessage($statusCode)
    {
        $errorMessages = [
            // 通用错误
            1 => '服务器内部错误',
            2 => '请求参数非法',
            3 => '权限校验失败',
            4 => '配额校验失败',
            5 => 'ak不存在或者非法',
            101 => '服务禁用',
            102 => '不通过白名单或者安全码不对',

            // 地理编码API错误
            1001 => '服务器内部错误',
            1002 => '请求参数非法',
            1003 => '权限校验失败',
            1004 => '配额校验失败',
            1005 => 'ak不存在或者非法',
            1006 => '服务不存在或者非法',
            1101 => '服务禁用',
            1102 => '不通过白名单或者安全码不对',

            // Place API错误
            240 => 'APP 服务被禁用',
            250 => '用户不存在',
            251 => '用户key不存在',
            252 => '用户key过期',
            260 => 'APP不存在，AK有误请检查再重试',
            261 => 'APP被用户自己禁用，请在控制台解禁',
            262 => 'APP被管理员删除',

            // 其他常见错误
            300 => '请求参数信息有误',
            301 => '关键词有误',
            302 => '请求地区有误',
            401 => '当前IP无访问权限',
            402 => '当前SN无访问权限'
        ];

        return $errorMessages[$statusCode] ?? "未知错误 (状态码: {$statusCode})";
    }

    /**
     * 获取详细的交通信息（公交线路和地铁线路）
     */
    private function getDetailedTransitInfo($longitude, $latitude, $apiKey, $radius = 1000, $maxResults = 5)
    {
        try {
            $transitInfo = '';

            // 1. 获取公交站点信息
            $busStops = $this->getBaiduTransitStops($longitude, $latitude, $apiKey, '公交站', $radius, $maxResults);
            if (!empty($busStops)) {
                $transitInfo .= "**附近公交站：** ";
                $busStopNames = [];
                foreach ($busStops as $stop) {
                    $stopInfo = $stop['name'];
                    if (isset($stop['distance'])) {
                        $stopInfo .= '(' . round($stop['distance']) . 'm)';
                    }
                    $busStopNames[] = $stopInfo;
                }
                $transitInfo .= implode('、', $busStopNames) . "\n";

                // 获取公交线路信息
                $busLines = $this->getBusLinesFromStops($busStops, $apiKey);
                if (!empty($busLines)) {
                    $transitInfo .= "**经过公交线路：** " . implode('、', array_unique($busLines)) . "\n";
                }
            }

            // 2. 获取地铁站点信息
            $subwayStops = $this->getBaiduTransitStops($longitude, $latitude, $apiKey, '地铁站', $radius * 2, 3);
            if (!empty($subwayStops)) {
                $transitInfo .= "**附近地铁站：** ";
                $subwayStopNames = [];
                foreach ($subwayStops as $stop) {
                    $stopInfo = $stop['name'];
                    if (isset($stop['distance'])) {
                        $stopInfo .= '(' . round($stop['distance']) . 'm)';
                    }
                    $subwayStopNames[] = $stopInfo;
                }
                $transitInfo .= implode('、', $subwayStopNames) . "\n";

                // 获取地铁线路信息
                $subwayLines = $this->getSubwayLinesFromStops($subwayStops, $apiKey);
                if (!empty($subwayLines)) {
                    $transitInfo .= "**地铁线路：** " . implode('、', array_unique($subwayLines)) . "\n";
                }
            }

            // 3. 获取交通路线建议
            $routeSuggestion = $this->getRouteSuggestion($longitude, $latitude, $apiKey);
            if ($routeSuggestion) {
                $transitInfo .= "**交通建议：** " . $routeSuggestion . "\n";
            }

            return $transitInfo;

        } catch (\Exception $e) {
            $this->writeLog("获取详细交通信息失败: " . $e->getMessage(), 'error');
            return null;
        }
    }

    /**
     * 获取公交/地铁站点详细信息
     */
    private function getBaiduTransitStops($longitude, $latitude, $apiKey, $query, $radius = 1000, $pageSize = 5)
    {
        try {
            $url = "https://api.map.baidu.com/place/v2/search";
            $params = [
                'ak' => $apiKey,
                'output' => 'json',
                'query' => $query,
                'location' => $latitude . ',' . $longitude,
                'radius' => $radius,
                'page_size' => $pageSize,
                'page_num' => 0,
                'scope' => 2 // 获取详细信息
            ];

            $response = $this->httpRequest($url, $params);
            $data = json_decode($response, true);

            $this->writeLog("百度交通站点API响应: " . $response, 'debug');

            if ($data && $data['status'] == 0 && isset($data['results']) && !empty($data['results'])) {
                $stops = [];
                foreach ($data['results'] as $result) {
                    $stop = [
                        'name' => $result['name'],
                        'address' => $result['address'] ?? '',
                        'distance' => $result['detail_info']['distance'] ?? null,
                        'uid' => $result['uid'] ?? '',
                        'detail_info' => $result['detail_info'] ?? []
                    ];
                    $stops[] = $stop;
                }
                return $stops;
            }

            // 处理API错误
            if ($data && isset($data['status']) && $data['status'] != 0) {
                $errorMsg = $this->getBaiduApiErrorMessage($data['status']);
                $this->writeLog("百度交通站点API错误 - 查询: {$query}, 状态码: {$data['status']}, 错误信息: {$errorMsg}", 'error');
            }

            return [];

        } catch (\Exception $e) {
            $this->writeLog("获取交通站点失败: " . $e->getMessage(), 'error');
            return [];
        }
    }

    /**
     * 从公交站点获取公交线路信息
     */
    private function getBusLinesFromStops($busStops, $apiKey)
    {
        $busLines = [];

        foreach ($busStops as $stop) {
            // 从站点详细信息中提取公交线路
            $busLines[]=$stop["name"].str_replace(";","、",$stop["address"]).";";

            // 如果有UID，可以调用详情API获取更多信息
            if (!empty($stop['uid'])) {
                $detailLines = $this->getStopDetailLines($stop['uid'], $apiKey);
                if (!empty($detailLines)) {
                    $busLines = array_merge($busLines, $detailLines);
                }
            }
        }

        return array_unique($busLines);
    }

    /**
     * 从地铁站点获取地铁线路信息
     */
    private function getSubwayLinesFromStops($subwayStops, $apiKey)
    {
        $subwayLines = [];

        foreach ($subwayStops as $stop) {
            // 从站点名称中提取地铁线路信息
            $name = $stop['name'];

            // 匹配地铁线路模式
            if (preg_match_all('/(地铁)?([1-9]\d*号线|[A-Z]线)/u', $name, $matches)) {
                foreach ($matches[2] as $line) {
                    $subwayLines[] = $line;
                }
            }

            // 从详细信息中提取
            if (isset($stop['detail_info']['tag'])) {
                $tag = $stop['detail_info']['tag'];
                if (preg_match_all('/([1-9]\d*号线|[A-Z]线)/u', $tag, $matches)) {
                    $subwayLines = array_merge($subwayLines, $matches[1]);
                }
            }
        }

        return array_unique($subwayLines);
    }

    /**
     * 获取站点详细线路信息
     */
    private function getStopDetailLines($uid, $apiKey)
    {
        try {
            $url = "https://api.map.baidu.com/place/v2/detail";
            $params = [
                'ak' => $apiKey,
                'output' => 'json',
                'uid' => $uid,
                'scope' => 2
            ];

            $response = $this->httpRequest($url, $params);
            $data = json_decode($response, true);

            if ($data && $data['status'] == 0 && isset($data['result'])) {
                $lines = [];
                $result = $data['result'];

                // 从详细信息中提取线路
                if (isset($result['detail_info']['tag'])) {
                    $tag = $result['detail_info']['tag'];
                    if (preg_match_all('/(\d+路|[A-Z]\d+|快\d+|夜\d+)/u', $tag, $matches)) {
                        $lines = array_merge($lines, $matches[1]);
                    }
                }

                return $lines;
            }

            return [];

        } catch (\Exception $e) {
            $this->writeLog("获取站点详细线路失败: " . $e->getMessage(), 'error');
            return [];
        }
    }

    /**
     * 获取交通路线建议
     */
    private function getRouteSuggestion($longitude, $latitude, $apiKey)
    {
        try {
            // 获取附近主要交通枢纽
            $majorStops = $this->getBaiduPOI($longitude, $latitude, $apiKey, '交通枢纽', 3000, 2);

            $suggestions = [];

            if ($majorStops) {
                $suggestions[] = "可通过" . $majorStops . "等交通枢纽换乘";
            }

            // 根据距离给出建议
            $busStops = $this->getBaiduTransitStops($longitude, $latitude, $apiKey, '公交站', 500, 1);
            if (!empty($busStops) && isset($busStops[0]['distance'])) {
                $distance = $busStops[0]['distance'];
                if ($distance < 200) {
                    $suggestions[] = "步行即可到达公交站";
                } elseif ($distance < 500) {
                    $suggestions[] = "步行约" . ceil($distance/100) . "分钟到达公交站";
                } else {
                    $suggestions[] = "建议骑行或打车前往公交站";
                }
            }

            return implode('，', $suggestions);

        } catch (\Exception $e) {
            $this->writeLog("获取交通建议失败: " . $e->getMessage(), 'error');
            return null;
        }
    }

    /**
     * 生成模拟教学点详情
     */
    private function generateMockOcationDetail($prompt)
    {
        // 提取教学点信息
        $name = '';
        $level = '';

        if (preg_match('/\*\*教学点名称：\*\*\s*(.+?)(?:\n|$)/u', $prompt, $matches)) {
            $name = trim($matches[1]);
        }

        if (preg_match('/\*\*级别：\*\*\s*(.+?)(?:\n|$)/u', $prompt, $matches)) {
            $level = trim($matches[1]);
        }

        // 判断是否是简介生成
        $isIntro = strpos($prompt, '50字以内') !== false;

        if ($isIntro) {
            // 生成简短介绍
            return "{$name}是一个环境优美、设施完善的{$level}，提供专业教学服务和舒适学习环境，欢迎各位学员前来学习。";
        }

        // 生成详细介绍（包含交通信息）
        $content = "";
        $content .= "{$name}坐落于城市便利地段，是一个环境优美、设施完善的{$level}。教学点内配备现代化教学设备，包括多媒体教室、专业音响系统和舒适的学习环境。\n\n";

        // 添加交通信息
        $content .= "**交通便利：**\n";
        $content .= "• 附近公交站：民族大道中(500m)、东葛路口(800m)\n";
        $content .= "• 经过公交线路：6路、34路、79路、213路、B01路\n";
        $content .= "• 附近地铁站：民族大道站(1.2km)、东葛路站(1.5km)\n";
        $content .= "• 地铁线路：1号线、2号线\n";
        $content .= "• 交通建议：可通过朝阳广场等交通枢纽换乘，步行约5分钟到达公交站\n\n";

        $content .= "我们的教学点秉承\"以学员为中心\"的教育理念，致力于为各年龄段学员提供高质量的教育服务。教室宽敞明亮，通风良好，为学员创造了舒适的学习氛围。\n\n";
        $content .= "教学点周边生活配套完善，附近有万象城、航洋国际等购物中心，以及各类餐饮和生活服务设施，为学员提供便利的学习环境。\n\n";
        $content .= "无论您是参加哪类课程，我们的教学点都将为您提供最佳的学习体验，欢迎各位学员前来参观和学习。（不要提到 市级 市一级 市二级 教学点ID 学费 收费 等字眼）";

        return $content;
    }

    /**
     * 生成模拟班级介绍
     */
    private function generateMockClassIntro($prompt)
    {
        // 提取班级信息
        $title = '';
        $subject = '';
        $institution = '';
        $grade = '';

        if (preg_match('/\*\*班级名称：\*\*\s*(.+?)(?:\n|$)/u', $prompt, $matches)) {
            $title = trim($matches[1]);
        }

        if (preg_match('/\*\*课程类别：\*\*\s*(.+?)(?:\n|$)/u', $prompt, $matches)) {
            $subject = trim($matches[1]);
        }

        if (preg_match('/\*\*所属机构：\*\*\s*(.+?)(?:\n|$)/u', $prompt, $matches)) {
            $institution = trim($matches[1]);
        }

        if (preg_match('/\*\*年级：\*\*\s*(.+?)(?:\n|$)/u', $prompt, $matches)) {
            $grade = trim($matches[1]);
        }

        // 检查是否包含教学点介绍
        $hasOcationIntro = strpos($prompt, '## 教学点介绍') !== false;

        $content = "<div class='ai-generated-content'>\n";

        if ($title) {
            $content .= "<p>欢迎加入<strong>{$title}</strong>！</p>\n\n";
        }

        // 如果有教学点介绍，添加相关内容
        if ($hasOcationIntro) {
            $content .= "<p>我们的班级位于优质的教学环境中，拥有现代化的教学设施和舒适的学习空间，为学员提供最佳的学习体验。</p>\n\n";
        }
        
        $content .= "<p>我们是一个充满活力和创新精神的班级";
        if ($institution) {
            $content .= "，隶属于{$institution}";
        }
        if ($subject) {
            $content .= "，专注于{$subject}领域的学习与实践";
        }
        $content .= "。</p>\n\n";
        
        $content .= "<p>在这里，我们致力于：</p>\n";
        $content .= "<ul>\n";
        $content .= "<li><strong>专业学习</strong>：系统掌握专业知识，培养扎实的理论基础</li>\n";
        $content .= "<li><strong>实践能力</strong>：通过项目实战，提升动手能力和解决问题的能力</li>\n";
        $content .= "<li><strong>团队合作</strong>：营造互帮互助的学习氛围，共同进步</li>\n";
        $content .= "<li><strong>创新思维</strong>：鼓励创新思考，培养批判性思维</li>\n";
        $content .= "</ul>\n\n";
        
        $content .= "<p>我们拥有优秀的师资团队和完善的教学设施，为每一位同学提供最好的学习环境。期待与你一起在知识的海洋中探索，共同创造美好的学习时光！</p>(不要提到 市级 市一级 市二级 教学点ID 学费 收费 等敏感字眼)\n";
        
        $content .= "</div>";
        
        return $content;
    }

    /**
     * 生成模拟教学点详情
     */
    private function generateMockOcationDetail2($prompt)
    {
        $content = "<div class='ai-generated-content'>\n";
        $content .= "<h3>教学点介绍</h3>\n";
        $content .= "<p>本教学点是一个现代化的教育培训基地，致力于为学员提供优质的教育服务。</p>\n\n";
        
        $content .= "<h4>教学特色</h4>\n";
        $content .= "<ul>\n";
        $content .= "<li>专业的师资团队，丰富的教学经验</li>\n";
        $content .= "<li>完善的教学设施，先进的教学设备</li>\n";
        $content .= "<li>灵活的课程安排，满足不同需求</li>\n";
        $content .= "<li>贴心的学员服务，全程跟踪指导</li>\n";
        $content .= "</ul>\n\n";
        
        $content .= "<p>我们秉承'以学员为中心'的教育理念，不断创新教学方法，为每一位学员的成长成才保驾护航。</p>(不要提到 市级 市一级 市二级 教学点ID 学费 收费 等敏感字眼)\n";
        $content .= "</div>";
        
        return $content;
    }

    /**
     * 生成模拟通用内容
     */
    private function generateMockGeneralContent($prompt)
    {
        $content = "<div class='ai-generated-content'>\n";
        $content .= "<p>基于您提供的信息，我们为您生成了以下内容：</p>\n\n";
        
        // 简单的关键词提取和内容生成
        $keywords = [];
        if (preg_match_all('/[\u4e00-\u9fa5]{2,}/u', $prompt, $matches)) {
            $keywords = array_slice(array_unique($matches[0]), 0, 5);
        }
        
        if (!empty($keywords)) {
            $content .= "<p>关键要素：" . implode('、', $keywords) . "</p>\n\n";
        }
        
        $content .= "<p>这是一个充满潜力的主题，值得我们深入探讨和研究。通过系统的分析和实践，我们可以获得更深入的理解和认识。</p>(不要提到 市级 市一级 市二级 教学点ID 学费 收费 等敏感字眼)\n\n";
        
        $content .= "<p>建议从以下几个方面进行进一步的发展：</p>\n";
        $content .= "<ul>\n";
        $content .= "<li>深入研究相关理论基础</li>\n";
        $content .= "<li>结合实际情况进行应用</li>\n";
        $content .= "<li>持续优化和改进</li>\n";
        $content .= "<li>加强交流与合作</li>\n";
        $content .= "</ul>\n";
        
        $content .= "</div>";
        
        return $content;
    }

    /**
     * 获取教学点课程数据
     */
    private function getOcationCoursesData($ocationId)
    {
        // 返回模拟的课程数据
        return [
            'ocation_id' => $ocationId,
            'courses' => [
                [
                    'id' => 1,
                    'name' => '计算机基础课程',
                    'content' => '本课程涵盖计算机基础知识，包括计算机组成原理、操作系统、数据结构等核心内容。',
                    'intro' => '适合初学者的计算机入门课程',
                    'category_name' => '计算机科学',
                    'has_content' => true,
                    'content_length' => 50,
                    'is_long_term' => true
                ],
                [
                    'id' => 2,
                    'name' => '编程实践班',
                    'content' => '通过实际项目开发，掌握编程技能，培养解决实际问题的能力。',
                    'intro' => '注重实践的编程课程',
                    'category_name' => '软件开发',
                    'has_content' => true,
                    'content_length' => 40,
                    'is_long_term' => false
                ]
            ],
            'total_count' => 2,
            'search_scope' => '当前教学点',
            'table_info' => '模拟数据'
        ];
    }

    /**
     * 清理和修复UTF-8编码
     */
    private function sanitizeUTF8($text)
    {
        if (empty($text)) {
            return $text;
        }
        
        // 检查是否为有效的UTF-8
        if (!mb_check_encoding($text, 'UTF-8')) {
            // 尝试从其他编码转换
            $text = mb_convert_encoding($text, 'UTF-8', 'auto');
        }
        
        // 移除或替换无效的UTF-8字符
        $text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');
        
        // 移除控制字符（除了换行、回车、制表符）
        $text = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $text);
        
        // 移除BOM标记
        $text = str_replace("\xEF\xBB\xBF", '', $text);
        
        // 确保字符串以UTF-8编码结束
        return trim($text);
    }

    /**
     * 获取教学点课程信息用于AI提示词生成
     * @param int $ocation_id 教学点ID
     * @return string 格式化的课程信息
     */
    private function getOcationCourseInfo($ocation_id)
    {
        try {
            // 获取该教学点及其所有子教学点的ID
            $ocationIds = $this->getAllSubOcationIds($ocation_id);

            // 调用baseCourseQuery方法获取近期课程
            $eventController = new \app\api\controller\v1\Event();
            $params = [
                'page' => 1,
                'limit' => 10, // 获取最近10个课程
                'ocation_ids' => $ocationIds,
                'include_sub_ocations' => true,
                'time_filter' => 'recent', // 获取最近的课程
                'order' => 'full_start_time asc', // 按开始时间排序
                'current_day' => '2025-05-25'
            ];

            $courses = $eventController->baseCourseQuery($params);

            if (empty($courses)) {
                return "暂无近期课程安排。\n";
            }

            $courseInfo = "";
            $mainOcationCourses = [];
            $subOcationCourses = [];

            // 分类处理主教学点和子教学点的课程
            foreach ($courses as $course) {
                $courseData = $this->formatCourseInfo($course);

                if ($course['ocation_id'] == $ocation_id) {
                    $mainOcationCourses[] = $courseData;
                } else {
                    if (!isset($subOcationCourses[$course['ocation_name']])) {
                        $subOcationCourses[$course['ocation_name']] = [];
                    }
                    $subOcationCourses[$course['ocation_name']][] = $courseData;
                }
            }

            // 格式化主教学点课程信息
            if (!empty($mainOcationCourses)) {
                $courseInfo .= "**本教学点近期课程：**\n";
                foreach ($mainOcationCourses as $courseData) {
                    $courseInfo .= "- " . $courseData . "\n";
                }
            }

            // 格式化子教学点课程信息
            if (!empty($subOcationCourses)) {
                $courseInfo .= "\n**子教学点近期课程：**\n";
                foreach ($subOcationCourses as $ocationName => $courses) {
                    $courseInfo .= "• {$ocationName}：\n";
                    foreach ($courses as $courseData) {
                        $courseInfo .= "  - " . $courseData . "\n";
                    }
                }
            }

            return $courseInfo;

        } catch (\Exception $e) {
            $this->writeLog("获取教学点课程信息失败: " . $e->getMessage(), 'error');
            return "课程信息获取中，请稍后查看。\n";
        }
    }

    /**
     * 格式化单个课程信息
     * @param array $course 课程数据
     * @return string 格式化的课程信息
     */
    private function formatCourseInfo($course)
    {
        $courseInfo = "";

        // 课程名称
        $courseName = $course['className'] ?? $course['course_name'] ?? '未知课程';
        $courseInfo .= $courseName;

        // 课程类型
        if (isset($course['table_type'])) {
            $courseType = $course['table_type'] == 1 ? '学校课程' : '社区课程';
            $courseInfo .= "（{$courseType}）";
        }

        // 课程时间
        if (isset($course['date']) && isset($course['start_time']) && isset($course['end_time'])) {
            $courseInfo .= " - " . $course['date'] . " " . $course['start_time'] . "-" . $course['end_time'];
        } elseif (isset($course['start_date'])) {
            $courseInfo .= " - " . date('Y-m-d H:i', strtotime($course['start_date']));
        }

        // 课程地点
        if (isset($course['ocation_name'])) {
            $courseInfo .= " - " . $course['ocation_name'];
        }

        // 课程学科
        if (isset($course['subject'])) {
            $courseInfo .= " - " . $course['subject'];
        }

        // 获取教师信息
        $teacherName = $this->getTeacherName($course);
        if ($teacherName) {
            $courseInfo .= " - 教师：" . $teacherName;
        }

        return $courseInfo;
    }

    /**
     * 获取课程教师姓名
     * @param array $course 课程数据
     * @return string 教师姓名
     */
    private function getTeacherName($course)
    {
        try {
            if (!isset($course['class_id'])) {
                return '';
            }

            // 通过eb_course表和eb_class_teacher表获取教师信息
            $teacher = \think\Db::name('eb_course')
                ->alias('c')
                ->join('eb_class_teacher t', 'c.teacher_id = t.id', 'LEFT')
                ->join('user u', 't.teacher_id = u.id', 'LEFT')
                ->where('c.class_id', $course['class_id'])
                ->field('u.nickname, u.realname, t.name as teacher_name')
                ->find();

            if ($teacher) {
                // 优先使用教师表中的姓名，其次是用户真实姓名，最后是昵称
                return $teacher['teacher_name'] ?: $teacher['realname'] ?: $teacher['nickname'] ?: '';
            }

            return '';

        } catch (\Exception $e) {
            $this->writeLog("获取教师信息失败: " . $e->getMessage(), 'error');
            return '';
        }
    }

    /**
     * 获取教学点及其所有子教学点的ID
     * @param int $ocation_id 教学点ID
     * @return array 教学点ID数组
     */
    private function getAllSubOcationIds($ocation_id)
    {
        try {
            $ocationIds = [$ocation_id];

            // 递归获取所有子教学点
            $subOcations = \think\Db::name('fa_ocation')
                ->where('pid', $ocation_id)
                ->where('status', 1)
                ->column('id');

            foreach ($subOcations as $subId) {
                $ocationIds = array_merge($ocationIds, $this->getAllSubOcationIds($subId));
            }

            return array_unique($ocationIds);

        } catch (\Exception $e) {
            $this->writeLog("获取子教学点ID失败: " . $e->getMessage(), 'error');
            return [$ocation_id];
        }
    }

    /**
     * 增强班级介绍提示词
     * @param string $originalPrompt 原始提示词
     * @return string 增强后的提示词
     */
    private function enhanceClassIntroPrompt($originalPrompt)
    {
        try {
            // 从原始提示词中提取教学点ID
            $ocationId = $this->extractOcationIdFromPrompt($originalPrompt);

            if ($ocationId) {
                // 获取教学点的详细信息（包含课程信息）
                $ocation = \think\Db::name('fa_ocation')->where('id', $ocationId)->find();

                if ($ocation) {
                    // 构建增强的提示词
                    $enhancedPrompt = $originalPrompt . "\n\n";
                    $enhancedPrompt .= "## 教学点详细信息\n";
                    $enhancedPrompt .= "**教学点名称：** " . $ocation['name'] . "\n";
                    $enhancedPrompt .= "**教学点地址：** " . $ocation['address'] . "\n";

                    // 添加教学点介绍（如果存在）
                    if (!empty($ocation['content'])) {
                        $enhancedPrompt .= "**教学点介绍：** " . $ocation['content'] . "\n";
                    }

                    // 获取并添加课程信息
                    $courseInfo = $this->getOcationCourseInfo($ocationId);
                    if (!empty($courseInfo)) {
                        $enhancedPrompt .= "\n## 教学点近期课程安排\n";
                        $enhancedPrompt .= $courseInfo;
                    }

                    $enhancedPrompt .= "\n## 生成要求\n";
                    $enhancedPrompt .= "请结合以上教学点信息和课程安排，生成一个专业、有吸引力的班级介绍。\n";
                    $enhancedPrompt .= "要求：\n";
                    $enhancedPrompt .= "1. 突出教学点的地理位置优势,交通方便性、课程安排、课程内容、教师团队、学生体验、学生评价、学生反馈、学生评价、学生反馈、学生评价、学生反馈、学生评价、学生反馈、学生评价、学生反馈、学生评价、学生反馈、\n";
                    $enhancedPrompt .= "2. 如果有相关信息，体现丰富的课程安排和教学活动\n";
                    $enhancedPrompt .= "3. 如果有相关信息，展现专业的教学环境和师资力量\n";
                    $enhancedPrompt .= "4. 如果有相关信息，语言要温馨、专业、具有吸引力\n";
                    $enhancedPrompt .= "5. 不要提到 市级 市一级 市二级 教学点ID 学费 收费 等敏感字眼\n";
                    $enhancedPrompt .= "6. 字数控制在2200-2400字之间\n";

                    $this->writeLog("班级介绍提示词已增强，包含教学点和课程信息");
                    return $enhancedPrompt;
                }
            }

            $this->writeLog("无法提取教学点ID，使用原始提示词");
            return $originalPrompt;

        } catch (\Exception $e) {
            $this->writeLog("增强班级介绍提示词失败: " . $e->getMessage(), 'error');
            return $originalPrompt;
        }
    }

    /**
     * 从提示词中提取教学点ID
     * @param string $prompt 提示词
     * @return int|null 教学点ID
     */
    private function extractOcationIdFromPrompt($prompt)
    {
        try {
            // 尝试从提示词中匹配教学点ID的模式
            // 常见模式：教学点ID：123、ocation_id: 123、教学点：123等
            $patterns = [
                '/教学点ID[：:]\s*(\d+)/',
                '/ocation_id[：:]\s*(\d+)/',
                '/教学点[：:]\s*(\d+)/',
                '/location_id[：:]\s*(\d+)/',
                '/地点ID[：:]\s*(\d+)/'
            ];

            foreach ($patterns as $pattern) {
                if (preg_match($pattern, $prompt, $matches)) {
                    return intval($matches[1]);
                }
            }

            // 如果没有找到明确的ID模式，尝试从教学点名称匹配
            if (preg_match('/教学点[：:]?\s*([^，,。.\n]+)/', $prompt, $matches)) {
                $ocationName = trim($matches[1]);
                $ocation = \think\Db::name('fa_ocation')
                    ->where('name', 'like', '%' . $ocationName . '%')
                    ->find();
                if ($ocation) {
                    return $ocation['id'];
                }
            }

            return null;

        } catch (\Exception $e) {
            $this->writeLog("提取教学点ID失败: " . $e->getMessage(), 'error');
            return null;
        }
    }

    /**
     * 写入日志
     */
    private function writeLog($message, $level = 'info')
    {
        $logFile = $_SERVER["DOCUMENT_ROOT"] . "/../runtime/log/ai_helper.log";
        $logMessage = date('Y-m-d H:i:s') . " [{$level}] " . $message . "\n";
        file_put_contents($logFile, $logMessage, FILE_APPEND | LOCK_EX);
    }
}
